package base.world;

import java.awt.Graphics2D;
import java.util.ArrayList;

import base.living.ILiving;
import base.render.Render;

public abstract class World extends WorldUtil implements IWorldRunnable
{
	private boolean runWorld = true;
	
	private ArrayList<ILiving> spawnList = new ArrayList<ILiving>();
	private ArrayList<ILiving> dumpList = new ArrayList<ILiving>();
	
	protected ArrayList<ILiving> livingList = new ArrayList<ILiving>();
	protected ArrayList<ILiving> trashList = new ArrayList<ILiving>();
	
	/**Updates and registers all newly-created objects this loop with the world*/
	public void updateLivingCreation()
	{
		for(ILiving obj : this.spawnList)
		{
			this.livingList.add(obj);
			this.dumpList.add(obj);
		}
		
		this.cleanDump();
	}
	
	/**Registers ILiving object with the world*/
	public ILiving livingCreate(ILiving par1Living)
	{
		return this.spawnList.add(par1Living) ? par1Living : null;
	}
	
	public void update()
	{
		if (!runWorld)
		{
			this.cleanDump();
			this.cleanTrash();
			return;
		}
		
		this.updateLivingCreation();
		
		for(ILiving obj : this.livingList)
		{
			if (!obj.isDead())
			{
				obj.onUpdate();
			}
			else
			{
				this.trashList.add(obj);
			}
		}
		
		this.cleanTrash();
	}
	
	public void render(Graphics2D par1Graphics)
	{
		for(ILiving obj : this.livingList)
		{
			if (obj instanceof Render)
			{
				((Render)obj).onPreRender(par1Graphics);
			}
		}
		
		for(ILiving obj : this.livingList)
		{
			if (obj instanceof Render)
			{
				((Render)obj).onRender(par1Graphics);
			}
		}
	}
	
	/**Removes all objects and terminates world updates*/
	public void destroyWorld()
	{
		for(ILiving obj : this.spawnList)
		{
			this.dumpList.add(obj);
		}
		
		for(ILiving obj : this.livingList)
		{
			this.trashList.add(obj);
		}
		
		this.runWorld = false;
	}
	
	protected void cleanTrash()
	{
		for(ILiving obj : this.trashList)
		{
			obj.onDestroy();
			this.livingList.remove(obj);
		}
		
		this.trashList.clear();
	}
	
	protected void cleanDump()
	{
		for(ILiving obj : this.dumpList)
		{
			this.spawnList.remove(obj);
		}
		
		this.dumpList.clear();
	}
	
	/**Returns if update list contains object*/
	public boolean doesLivingExist(ILiving par1Living)
	{
		return this.livingList.contains(par1Living);
	}
	
	/**If able to remove world from update*/
	public boolean canClearWorld()
	{
		return this.livingList.isEmpty() || this.spawnList.isEmpty() || this.trashList.isEmpty() || this.dumpList.isEmpty();
	}
}